<template>
  <view class="canvas-style">
    <canvas :style="{width: painting.width+'px', height:painting.height + 'px'}" :canvas-id="'myCanvas'+ canvasId"></canvas>
  </view>
</template>
<script>
export default {
  props: {
    canvasId: {
      type: String,
      default: '1'
    },
    rect: {
      type: Object,
      default: () => {
        return {
          width: 750,
          height: 1334
        }
      }
    }
  },
  data() {
    return {
      ctx: null,
      imagList: [],
      textList: [],
      rectList: [],
      callback: null,
      painting: {
        canvasId: '',
        width: 100, // canvas的宽高  px为单位
        height: 100,
        views: [
          // {
          //   style: 'image', // 普通图片1    // 绘制截图 3
          //   url: '',
          //   top: 0,
          //   left: 0,
          //   width: 0,
          //   height: 0,
          //   type: 1, // 1 2 3
          // },
          // {
          //   style: 'text',
          //   content: '', // 绘制文本
          //   color: '', // 颜色
          //   fontSize: 0, // 字体大小
          //   textAlign: 'left', // 文字对齐方式
          //   lineHeight: 20, // 多行文本中才能使用
          //   top: 0, // 文本左上角距离画板顶部的距离
          //   left: 0, // 文本左上角距离画板左侧的距离
          //   width: 0, // 和 MaxLineNumber 属性配套使用，width 就是达到换行的宽度
          //   breakWord: false, // 是否需要换行
          //   MaxLineNumber: 0, // 最大行数，只有设置 breakWord: true
          //   bolder: false, // 是否加粗
          //   textDecoration: 'none', // 显示中划线、下划线效果 underline（下划线）、line-through（中划线)
          // },
          // {
          //   style: 'rect', // 矩形 线条1  带圆弧的矩形2
          //   background: '', // 背景
          //   top: 0,
          //   left: 0,
          //   width: 0,
          //   height: 0,
          //   type: 1, // 1,
          //   border: 0,
          // }
        ]
      },
      startTime: 0
    }
  },
  created() {
    this.painting.width = this.rect.width
    this.painting.height = this.rect.height
  },
  mounted() {
    this.ctx = uni.createCanvasContext('myCanvas' + this.canvasId, this)
  },
  methods: {
    beginDraw(data, callback) {
      this.painting = data
      this.callback = callback
      this.imagList = []
      this.textList = []
      this.rectList = []
      this.startTime = new Date().getTime()
      console.log(data)
      console.log(this.ctx)
      if (this.ctx) {
        const views = this.painting.views
        for (let i = 0; i < views.length; i++) {
          if (views[i].style === 'image') {
            this.imagList.push(views[i])
          } else if (views[i].style === 'text') {
            this.textList.push(views[i])
          } else if (views[i].style === 'rect') {
            this.rectList.push(views[i])
          }
        }
        setTimeout(() => {
          this.handleImage()
        }, 100)
      }
    },
    // 处理所以图片
    handleImage() {
      const imageList = []
      this.imagList.forEach(item => {
        imageList.push(this.imageInfo(item))
      })
      console.log(imageList)
      Promise.all(imageList).then(res => {
        this.rectList.forEach(item => {
          this.drawRect(item)
        })
        res.forEach(item => {
          if (item.url) {
            this.drawImage(item)
          }
        })
        this.textList.forEach(item => {
          this.drawText(item)
        })
        console.log(new Date().getTime() - this.startTime)
        this.ctx.draw(false, () => {
          // https://developers.weixin.qq.com/community/develop/doc/00002a0eb7cab04fa7181534958c00?_at=1583228251379
          // 绘制完成后，由于canvas本身问题，安卓设备需要延迟保存临时目录，否则会出现文字样式混乱的情况
          setTimeout(() => {
            uni.canvasToTempFilePath({
              canvasId: 'myCanvas' + this.canvasId,
              destWidth: this.painting.width,
              destHeight: this.painting.height,
              quality: 0.5,
              success: (res) => {
                // #ifdef H5
                uni.uploadFile({
                  url: process.env.VUE_APP_MINI_API + '/bsnl-oss/appUpload', // 仅为示例，非真实的接口地址
                  filePath: res.tempFilePath,
                  formData: {
                    prefix: `TO_${1 * 24 * 60 * 60}`
                  },
                  success: (uploadFileRes) => {
                    const img = JSON.parse(uploadFileRes.data).data
                    this.callback && this.callback(img)
                  },
                  fail: (err) => {
                    this.callback && this.callback('')
                    console.log(err)
                  }
                })
                // #endif

                // #ifndef H5
                this.callback && this.callback(res.tempFilePath)
                console.log(new Date().getTime() - this.startTime)
                // #endif
              },
              fail: (err) => {
                this.callback && this.callback('')
                console.log(err)
              }
            }, this)
          }, 800)
        })
      })
    },
    // 绘制图片
    drawImage(param) {
      this.ctx.save()
      const { type = 1, url, top = 0, left = 0, width = 0, height = 0, border = [] } = param
      if (border.length === 4) {
        this.drawImageBorder({
          top: top,
          left: left,
          width: width,
          height: height,
          border: border
        })
      } else if (border.length !== 0) {
        console.log('border是个数组：代表是个角的半径： 左上  右上  右下 左下')
      }
      if (type === 1) {
        if (border.length === 4) {
          this.ctx.drawImage(url, 0, 0, width, height)
        } else {
          this.ctx.drawImage(url, left, top, width, height)
        }
      }
      this.ctx.restore()
    },
    drawImageBorder(param) {
      // border数组四个值，代表是个角的半径： 左上  右上  右下 左下
      const { top = 0, left = 0, width = 0, height = 0, border = [0, 0, 0, 0] } = param
      // 绘制圆弧边框的，两边的
      if (border.length === 4) {
        this.ctx.beginPath()
        this.ctx.translate(left, top)
        this.ctx.fillStyle = '#ffffff'
        if (border[0] !== 0) {
          this.ctx.arc(border[0], border[0], border[0], Math.PI, Math.PI * 3 / 2)
        } else {
          this.ctx.moveTo(0, 0)
        }
        this.ctx.lineTo(width - border[1], 0)
        if (border[1] !== 0) {
          this.ctx.arc(width - border[1], border[1], border[1], -Math.PI / 2, 0)
        }
        this.ctx.lineTo(width, height - border[2])

        if (border[2] !== 0) {
          this.ctx.arc(width - border[2], height - border[2], border[2], 0, Math.PI / 2)
        }
        this.ctx.lineTo(border[3], height)

        if (border[3] !== 0) {
          this.ctx.arc(border[3], height - border[3], border[3], Math.PI / 2, Math.PI)
        }
        this.ctx.lineTo(0, border[1])
        this.ctx.fill()
        this.ctx.clip()
      } else {
        console.log('border是个数组：代表是个角的半径： 左上  右上  右下 左下')
      }
    },
    getTextWidth(text, fontSize = 22) {
      this.ctx.font = `${fontSize}px sans-serif`
      return this.ctx.measureText(text).width
    },
    // 绘制rect
    drawRect(param) {
      this.ctx.save()
      const { background, type = 1, top = 0, left = 0, width = 0, height = 0, border = 0 } = param
      if (type === 2) {
        // 绘制圆弧边框的，两边的
        this.ctx.beginPath()
        this.ctx.translate(left, top)
        this.ctx.fillStyle = background
        // // // 从右下角顺时针绘制
        this.ctx.arc(width - border, height - border, border, -1 * Math.PI / 2, Math.PI / 2)
        this.ctx.lineTo(border, height)
        this.ctx.arc(border, height - border, border, Math.PI / 2, Math.PI * 3 / 2)
        this.ctx.lineTo(width - border, 0)
        this.ctx.fill()
      } else {
        this.ctx.fillStyle = background
        this.ctx.fillRect(left, top, width, height)
      }
      this.ctx.restore()
    },
    // 绘制文字
    drawText(param) {
      this.ctx.save()
      const {
        content = '',
        color = '#333',
        fontSize = 22,
        textAlign = 'left',
        lineHeight = 30,
        top = 0,
        left = 0,
        width = 0,
        breakWord = false,
        MaxLineNumber = 1,
        bolder = false,
        textDecoration = 'none',
        bg = {}
      } = param
      this.ctx.beginPath()
      this.ctx.setTextBaseline('top')
      this.ctx.setTextAlign(textAlign)
      this.ctx.fillStyle = color
      this.ctx.font = `${fontSize}px sans-serif`
      if (!breakWord) {
        this.drawTextLine(left, top, textDecoration, color, lineHeight, content, bg)
        this.ctx.fillText(content, left, top)
      } else {
        let fillText = ''
        let fillTop = top
        let lineNum = 1
        for (let i = 0; i < content.length; i++) {
          fillText += [content[i]]
          if (this.ctx.measureText(fillText).width > width) {
            if (lineNum === MaxLineNumber) {
              if (i !== content.length) {
                fillText = fillText.substring(0, fillText.length - 1) + '...'

                this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText, bg)
                this.ctx.fillText(fillText, left, fillTop)
                fillText = ''
                break
              }
            }

            this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText, bg)
            this.ctx.fillText(fillText, left, fillTop)
            fillText = ''
            fillTop += lineHeight
            lineNum++
          }
        }

        this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText, bg)
        this.ctx.fillText(fillText, left, fillTop)
      }

      if (bolder) {
        this.drawText({
          ...param,
          left: left + 0.3,
          top: top + 0.3,
          bolder: false,
          textDecoration: 'none'
        })
      }
      this.ctx.restore()
    },
    // 绘制文字下划线
    drawTextLine(left, top, textDecoration, color, fontSize, content, bg) {
      if (textDecoration === 'underline') {
        this.drawRect({
          background: color,
          top: top + fontSize * 0.8,
          left: left - 1,
          width: this.ctx.measureText(content).width + 3,
          height: 1
        })
      } else if (textDecoration === 'line-through') {
        this.drawRect({
          background: color,
          top: top + fontSize * 0.4,
          left: left - 1,
          width: this.ctx.measureText(content).width + 3,
          height: 1
        })
      } else if (textDecoration === 'background') {
        console.log(bg)
        this.drawRect({
          background: bg.color || '#ffffff',
          top: bg.top || top,
          left: bg.left || left,
          width: bg.width || this.ctx.measureText(content).width + 3,
          height: bg.height || 1
        })
      }
    },
    // 图片下载
    async imageInfo(item) {
      let url = item.url
      // #ifndef H5
      // 小程序图片下载
      if (item.url.indexOf('http') >= 0) {
        const imgResult = await this.downFile(url)
        if (imgResult.statusCode === 200) {
          url = imgResult.tempFilePath
        }
      }
      // #endif
      // 图片信息获取
      let sourceWidth = 0
      let sourceHeight = 0
      if ((url.indexOf('http') === -1 || item.type === 2) && url) {
        const res = await this.getImageInfo(url)
        sourceWidth = res.width
        sourceHeight = res.height
      }
      return {
        sourceWidth: sourceWidth,
        sourceHeight: sourceHeight,
        ...item,
        url
      }
    },
    // 获取图片信息
    getImageInfo(path) {
      return new Promise((resolve, reject) => {
        uni.getImageInfo({
          src: path,
          success: (res) => {
            resolve(res)
          },
          fail: (err) => {
            console.log(err)
            resolve('')
          }
        })
      })
    },
    // 下载图片
    downFile(path) {
      return new Promise((resolve, reject) => {
        uni.downloadFile({
          url: path,
          success: (res) => {
            if (res.statusCode === 200) {
              resolve(res)
            } else {
              console.log(res)
              resolve('')
            }
          },
          fail: (err) => {
            console.log(err)
            resolve('')
          }
        })
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.canvas-style {
  position: fixed;
  z-index: -1;
  left: 100%;
}
</style>
